#include "TcpConnection.h"
#include "EventLoop.h"
#include <sstream>

TcpConnection::TcpConnection(int fd, EventLoop *loop)
    : _sock(), _localAddr(getLocalAddress()), _peerAddr(getPeerAddress()), _socketIO(fd), _loop(loop)
{
}
string TcpConnection::receive()
{
    char buf[65535] = {0}; // 在栈上设置64kb大小
    int ret = _socketIO.readline(buf, sizeof(buf));
    return string(buf, ret);
}
void TcpConnection::send(const string & msg){
    if(msg.size() > 0){
        _socketIO.sendn(msg.c_str(),msg.size());
    }
}
int TcpConnection::readPacket(Packet & packet){
    return _socketIO.readPacket(packet);
}
bool TcpConnection::isClosed()
{
    char buf[20] = {0};
    return _socketIO.recvPeek(buf, sizeof(buf)) == 0;
}
void TcpConnection::shutdown()
{
    _sock.shutdownWirte();
}
string TcpConnection::toString()
{
    std::ostringstream oss;
    oss << "tcp" << _localAddr.ip() << ":" << _localAddr.port() << "->" << _peerAddr.ip() << ":" << _peerAddr.port();
    return oss.str();
}
InetAddress TcpConnection::getLocalAddress()
{
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    socklen_t len = sizeof(addr);
    int ret = getsockname(_sock.fd(), (struct sockaddr *)&addr, &len);
    if (ret < 0)
    {
        perror("getsockname");
    }
    return InetAddress(addr);
}
InetAddress TcpConnection::getPeerAddress()
{
    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));
    socklen_t len = sizeof(addr);
    int ret = getpeername(_sock.fd(), (struct sockaddr *)&addr, &len);
    if (ret < 0)
    {
        perror("getpeername");
    }
    return InetAddress(addr);
}
void TcpConnection::sendinLoop(const string & msg){
    if(_loop){
        _loop->runinLoop(std::bind(&TcpConnection::send,this,msg));
    }
}
void TcpConnection::sendinLoop(const TLV & tlv){
    int tlvlen = 8 + tlv._length;
    string msg;
    //拷贝内容
    msg.assign((const char *)&tlv,tlvlen);
    sendinLoop(msg);
}
void TcpConnection::handleCloseCallback()
{
    if (_onClose)
    {
        _onClose(shared_from_this());
    }
}
void TcpConnection::handleMessageCallback()
{
    if (_onMessage)
    {
        _onMessage(shared_from_this());
    }
}
void TcpConnection::handlenewConnectionCallback()
{
    if (_onConnection)
    {
        _onConnection(shared_from_this());
    }
}